<template>
	<cl-page>
		<view class="page">
			<view class="page-top" :style="'height:'+scrollHeight+'px'">
				<scroll-view :scroll-top="scrollTop" scroll-y class="list" :style="'height:'+scrollHeight+'px'"
					:scroll-with-animation="true">
					<!-- 为空时的占位符 -->
					<view class="empty" v-if="chatList[chatCurrent].list.length==0">
						<view class="empty-image">
							<image src="https://www.inktok.com/images/chats.png" mode="aspectFill"></image>
						</view>
						<view class="empty-title">
							Ask me anything
						</view>
						<view class="empty-desc">
							可进行对话、回答问题、实现情境应答等多种自然语言处理任务。
						</view>
						<view class="empty-desc">
							从下方选择一个问题并补充，或者输入您的内容
						</view>
					</view>
					<template v-else>
						<view class="item" :class="[item.role=='user' ? 'r' : 'l']"
							v-for="(item, index) in chatList[chatCurrent].list" :key="index">
							<view class="animate-absolute" v-if="item.loading&&item.role!='user'">
								<view class="animate-span">
									<view class="animate-ping"></view>
									<view class="relative inline-flex h-2 w-2 rounded-full bg-primary-60%"></view>
								</view>
							</view>
							<view class="content">
								<view class="text" v-if="item.content">
									<mp-html :selectable="true" :content="marked.parse(item.content)" />
								</view>
								<image class="image" :src="item.image" v-if="item.image" mode="widthFix"
									@tap="toPreview(item.image)" />
							</view>
						</view>
						<view class="item l" v-if="isLoading">
							<view class="animate-absolute">
								<view class="animate-span">
									<view class="animate-ping"></view>
									<view class="relative inline-flex h-2 w-2 rounded-full bg-primary-60%"></view>
								</view>
							</view>
							<view class="content">
								<view class="text">
									loading...
								</view>
							</view>
						</view>
						<view class="space"></view>
					</template>
				</scroll-view>
			</view>

			<view class="footer">
				<view class="footer-container" :class="keyboard>0?'footer-fiexd':''" :style="'bottom:'+keyboard+'px'">
					<view class="footer-input">
						<input v-model="question"  :placeholder="placeholder"
							@keyboardheightchange="keyboardheightchange" adjust-position="{{false}}"
							confirm-type="search" @blur="blur" @confirm="send" />
						<view class="send" :class="{ disabled: loading }" @tap="send">
							<image class="loading" src="/static/loading.svg" mode="aspectFill" v-if="loading" />
							<image class="btn" src="/static/send.svg" mode="aspectFill" v-else />
						</view>
					</view>
				</view>
				<view class="footer-item">
					<view class="footer-list" @click="showPopup()">
						Chat List
					</view>
					<view class="footer-list" @click="clearChat()">
						Clear chat
					</view>
				</view>
			</view>
		</view>
		<cl-confirm ref="Confirm"></cl-confirm>
		<!-- 普通弹窗 -->
		<cl-popup v-model="visible" :direction="'right'" :size="'100%'">
			<view class="max-w-full">
				<view class="max-w-static">
					<view class="items-start">
						<view class="items-start-text">
							History
						</view>
						<view class="items-start-icon" @click="closePopup">
							<cl-icon name="close"></cl-icon>
						</view>
					</view>
					<view class="popop-search">
						<cl-input placeholder="Search..." clearable @change="searchList">
							<template #prepend>
								<cl-icon name="search" color="rgb(107 114 128)"></cl-icon>
							</template>
						</cl-input>
					</view>
					<view class="popup-button popup-list" @click="addChatList">
						<cl-icon name="plus" color="#6b69f8"></cl-icon>
						新建会话
					</view>
				</view>
				<view class="popup-item">
					<view class="popup-list popup-item-list" :class="chatCurrent==index?'popup-current':''"
						v-for="(item,index) in chatList" :key="index">
						<view class="popup-item-list flex-1" @click="changeListCurrent(index)">
							<view class="popup-list-title" >
								{{item.title}}
							</view>
							<view class="flex">
								<view class="popup-list-time">
									{{moment(item.time).fromNow()}}
								</view>
							</view>
						</view>
						<view class="popup-list-icon" v-if="chatList.length>1&&!item.isEdit" @click="removeChatList(index)">
							<cl-icon name="close" />
						</view>
					</view>
				</view>
			</view>
		</cl-popup>
	</cl-page>
</template>

<script setup>
	import {
		onBeforeMount,
		onMounted,
		reactive,
		ref,
		nextTick,
		computed,
		watch,
		getCurrentInstance
	} from "vue";
	// import io from "@hyoga/uni-socket.io";
	import {
		useStore,
		useCool
	} from "/@/cool";
	import {
		getRect
	} from "/@/cool/utils";
	const {
		storage
	} = useCool();
	import {
		useUi
	} from "/@/ui";
	const ui = useUi();
	const {
		user
	} = useStore();
	import {
		marked
	} from "marked";
	import hljs from "highlight.js/lib/core";
	import "highlight.js/styles/monokai-sublime.css";
	import bash from "highlight.js/lib/languages/bash";
	import javascript from "highlight.js/lib/languages/javascript";
	import typescript from "highlight.js/lib/languages/typescript";
	import json from "highlight.js/lib/languages/json";
	import python from "highlight.js/lib/languages/python";
	import sql from "highlight.js/lib/languages/sql";
	import java from "highlight.js/lib/languages/java";
	import shell from "highlight.js/lib/languages/shell";
	import php from "highlight.js/lib/languages/php";
	import go from "highlight.js/lib/languages/go";
	hljs.registerLanguage("bash", bash);
	hljs.registerLanguage("javascript", javascript);
	hljs.registerLanguage("typescript", typescript);
	hljs.registerLanguage("json", json);
	hljs.registerLanguage("python", python);
	hljs.registerLanguage("sql", sql);
	hljs.registerLanguage("java", java);
	hljs.registerLanguage("shell", shell);
	hljs.registerLanguage("php", php);
	hljs.registerLanguage("go", go);
	import moment from 'moment';
	marked.setOptions({
		renderer: new marked.Renderer(),
		highlight: function(code) {
			return "<view class='code'>" + hljs.highlightAuto(code).value + "</view>";
		},
		pedantic: false,
		gfm: true,
		tables: true,
		breaks: false,
		sanitize: false,
		smartLists: true,
		smartypants: false,
		xhtml: false
	});

	let socket;
	const list = ref([]);
	const loading = ref(false);
	const question = ref("");
	const isLoading = ref(false)
	const scrollTop = ref(0);
	const mode = reactive({
		value: "text",
		list: [{
				value: "img"
			},
			{
				value: "text"
			}
		]
	});
	const placeholder = computed(() => {
		return mode.value == "text" ? "请描述你的问题，让AI帮你解答" : "请描述你的想法，让AI帮你画";
	});
	const keyboard = ref(0)
	const Confirm = ref < HTMLElement > ('Confirm')
	const visible = ref(false)
	const chatList = ref([{
		title: "New Chat",
		list: [],
		time: moment()
	}])
	const chatListCopy = ref([])
	const chatCurrent = ref(0)
	function blur(){
		keyboard.value = 0
	}
	// 搜索
	function searchList(res){
		console.log(storage.get('chatList').filter(item=>item.title.indexOf(res)!=-1))
		let list=storage.get('chatList').filter(item=>item.title.indexOf(res)!=-1)
		if(list.length>0){
			chatList.value=list
		}else{
			chatList.value=storage.get('chatList')
		}
		chatCurrent.value=0
	}
	// 显示历史记录
	function showPopup() {
		visible.value = true
	}
	// 关闭历史记录
	function closePopup() {
		visible.value = false
	}
	// 新增会话窗口
	function addChatList() {
		if (chatList.value.length >= 20) {
			ui.showToast("请清除部分记录后再尝试添加");
		} else {
			chatList.value.push({
				title: "New Chat",
				list: [],
				time: moment()
			})
		}
		setList()
	}
	//切换当前窗口 
	function changeListCurrent(index) {
		chatCurrent.value = index
		closePopup()
	}
	//删除聊天窗口
	function removeChatList(index) {
		if (index <= chatCurrent.value && index > 0) {
			chatCurrent.value--
		}
		chatList.value.splice(index, 1)
		storage.set('chatList', chatList.value)
	}
	//清除聊天记录
	function clearChat() {
		Confirm.value?.open({
			title: "提示",
			message: "确定要清空记录列表吗?",
			callback(action) {
				switch (action) {
					case "confirm":
						ui.showToast("清空成功");
						storage.remove('chatList')
						chatList.value = [{
							title: "New Chat",
							list: [],
							time: moment(),
							isEdit: false
						}]
						chatCurrent.value = 0
						break;

					case "cancel":
						break;

					case "close":
						break;
				}
			}
		});
	}
	
	//监听键盘高度事件
	function keyboardheightchange(event) {
		console.log(event)
		if (event.detail.height > 0) {
			keyboard.value = event.detail.height
		} else {
			keyboard.value = 0
		}
	}
	//链接socket
	async function connect() {
		if(!user.socket){
			return
		}
		user.socket.on(user.socketId, (message) => {
			console.log(message)
			let {code,msg}=message
			if(code==1000){
				let {
					detail,
					...temp
				} = msg
				let list = chatList.value[chatCurrent.value].list
				let isDetail = list.find(item => item.id == msg.id)
				let content = ""
				if (isDetail) {
					let index = list.findIndex(item => item.id == msg.id)
					if (msg.detail.choices[0].finish_reason == 'stop') {
						list[index].content = msg.text
						list[index].loading = false
						loading.value = false
					} else {
						list[index].content += msg.delta
					}
				} else {
					if (msg.detail.choices[0].finish_reason == 'stop') {
						content = msg.text
					} else {
						content += msg.delta ? msg.delta : ''
					}
					list.push({
						content,
						...temp,
						loading: true,
					})
				}
				isLoading.value = false
				content = ""
				setList()
				nextTick(() => {
					scrollToBottom();
				});
			}else{
				isLoading.value = false
				loading.value = false;
			}
		});
	}
	//保存会话列表
	function setList() {
		chatList.value[chatCurrent.value].time = moment()
		storage.set('chatList', chatList.value)
	}

	function send() {
		if (question.value) {
			if (!loading.value) {
				loading.value = true;
				let list = chatList.value[chatCurrent.value].list
				let array = []
				list.push({
					role: "user",
					content: question.value
				});
				chatList.value[chatCurrent.value].title=question.value
				list.forEach(item => {
					array.push({
						role: item.role,
						content: item.content
					})
				})
				user.socket.emit("gotMessage", {
					role:"user",
					userId: storage.get('userInfo').id,
					text:question.value,
					content:array
				});
				question.value = "";
				isLoading.value = true
				loading.value = true
				setList()
				nextTick(() => {
					scrollToBottom();
				});
			}
		}
	}

	function scrollToBottom() {
		scrollTop.value = 1000000 + parseInt(Math.random() * 100);
	}

	function toPreview(url) {
		wx.previewImage({
			urls: [url],
			current: url,
			showmenu: true
		});
	}
	const scrollHeight = ref(0)
	onBeforeMount(() => {
		uni.getSystemInfo({
			success: async (res) => {
				let footer = await getRect(".footer")
				scrollHeight.value = res.windowHeight - res.safeAreaInsets.bottom - footer.height
			}
		})
	})

	onMounted(async () => {
			console.log()
		connect();
		moment.locale('zh-cn', {
			relativeTime: {
				future: '%s内',
				past: '%s前',
				s: '几秒',
				ss: '%d秒',
				m: '1分钟',
				mm: '%d分钟',
				h: '1小时',
				hh: '%d小时',
				d: '1天',
				dd: '%d天',
				M: '1个月',
				MM: '%d个月',
				y: '1年',
				yy: '%d年'
			}
		})
		if (storage.get('chatList')) {
			if (storage.get('chatList').length > 0) {
				chatList.value = storage.get('chatList')
				if (storage.get('chatList').length + 1 < 20) {
					chatList.value.push({
						title: "New Chat",
						list: [],
						time: moment()
					})
					chatCurrent.value = storage.get('chatList').length
				} else {
					chatCurrent.value = storage.get('chatList').length - 1
				}
			}
		}
	});
</script>

<style lang="scss">
	.flex {
		display: flex;
		align-items: center;
	}

	.flex-1 {
		flex: 1
	}

	.page-content-search {
		color: rgb(112 114 129);
		font-weight: 600;
		font-size: 1rem;
		text-align: center;
		margin-bottom: 1rem;
	}

	.max-w-full {
		display: flex;
		flex-direction: column;
		height: 100%;

		.popup-item {
			flex: 1;
			overflow-y: auto;
		}

		.max-w-static {
			position: sticky;
			top: 0;
			left: 0;
			right: 0;
			background-color: #fff;
			z-index: 2;
		}

		.popup-list-time {
			color: rgb(156 163 175);
			font-size: .875rem;
		}

		.popup-list-icon {
			color: rgb(156 163 175);
			margin-left: 0.5rem;
		}

		.popup-item-list {
			display: flex;
			align-items: center;
			justify-content: space-between;

			.popup-list-title {
				flex: 1;
				display: -webkit-box;
				-webkit-line-clamp: 1;
				overflow: hidden;
				-webkit-box-orient: vertical;
			}
		}

		.popup-current {
			background-color: rgb(243 244 246);
			border-radius: 10rpx;
		}

		.popup-list {
			padding: 1rem;
			font-size: .875rem;
			border-top: 1px solid rgb(243 244 246)
		}
		.popup-list-input{
			flex:1;
			margin-right:40rpx;
		}
		.popup-button {
			color: #6b69f8;
		}

		.items-start {
			padding-top: 0.5rem;
			padding-left: .75rem;
			padding-right: .75rem;
			display: flex;
			justify-content: space-between;
			align-items: center;
			margin-bottom: 0.5em;

			.items-start-text {
				color: rgb(17 24 39);
				font-weight: 500;
				font-size: 1.125rem;
			}
		}

		.popop-search {
			padding-left: .5rem;
			padding-right: .5rem;
			margin: 1.5rem 0;
		}
	}

	page {
		height: 100vh;
	}

	$color-primary: rgba(255, 67, 18, 0.9);

	.page {
		display: flex;
		// flex: 1;
		flex-direction: column;

		.page-top {
			// flex: 1;
		}

		.list {
			width: 100%;
			height: 100%;

			.space {
				height: 50rpx;
			}

			.empty {
				width: 100%;
				height: 100%;
				background-color: rgb(255, 255, 255);
				padding: 2.5rem 20rpx 0;
				box-sizing: border-box;
				display: flex;
				flex-direction: column;
				align-items: center;
				text-align: center;

				.empty-image {
					width: 160rpx;
					height: 160rpx;

					image {
						width: 100%;
						height: 100%
					}
				}

				.empty-title {
					line-height: 1.5rem;
					color: rgb(17 20 45/var($-tw-text-opacity));
					font-weight: 800;
					margin-bottom: 0.5rem;
				}

				.empty-desc {
					font-size: .875rem;
					margin-bottom: 0.5rem;
					color: rgb(112 114 129/var($-tw-text-opacity));
				}
			}
		}
	}

	.list {
		// height: calc(100% - 90rpx);
		background-color: #f7f7f7;
		box-sizing: border-box;
		overflow: auto;

		.item {
			display: flex;
			padding: 20rpx 20rpx 10rpx;
			position: relative;

			.animate-absolute {
				position: absolute;
				top: 24rpx;
				left: 24rpx;
				z-index: 99;
				width: .5rem;
				height: .5rem;

				.animate-span {
					width: 100%;
					height: 100%;
					position: relative;

					.animate-ping {
						width: 100%;
						height: 100%;
						left: 0;
						right: 0;
						top: 0;
						bottom: 0;
						position: absolute;
						border-radius: 50%;
						background-color: #6b69f890;
						animation: ping 1s cubic-bezier(0, 0, .2, 1) infinite;

						@keyframes ping {

							75%,
							to {
								transform: scale(2);
								opacity: 0
							}
						}
					}

					.rounded-full {
						left: 0;
						right: 0;
						top: 0;
						bottom: 0;
						position: absolute;
						width: 100%;
						height: 100%;
						border-radius: 50%;
						background-color: #6b69f8;
					}
				}

			}

			.content {
				display: block;
				margin: 10rpx 10rpx 0 10rpx;
				font-size: 28rpx;
				background-color: #fff;
				max-width: 80%;
				border-radius: 0.25rem;
				color: rgb(55 65 81);
				box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -2px rgba(0, 0, 0, .1);

				.text {
					display: block;
					padding: 20rpx 30rpx;
					line-height: 40rpx;
					user-select: auto;
				}

				.image {
					position: relative;
					width: 400rpx;
					display: block;
					border: 1rpx solid #eee;
					border-radius: 6rpx;
				}

				:deep(.code) {
					display: block;
					background-color: #18222c;
					color: #fff;
					padding: 20rpx;
					margin-top: 20rpx;
					overflow: auto;
					border-radius: 10rpx;
					font-size: 24rpx;
				}
			}

			&.r {
				flex-direction: row-reverse;
			}
		}
	}

	.footer {
		width: 100%;
		border-top: 1rpx solid #e5e7eb;
		box-sizing: border-box;
		background-color: #fff;
		color: #fff;
		z-index: 9;
		transition: .5s;

		.footer-fiexd {
			position: fixed;
			left: 0;
			right: 0;
		}

		.footer-container {
			padding: 1rem .5rem;
			background-color: #fff;

			.footer-input {

				border-color: rgb(243 244 246);
				background-color: rgb(249 250 251);
				color: rgb(17 20 45/var($-tw-text-opacity));
				height: 42px;
				box-sizing: border-box;
				outline: 2px solid transparent;
				outline-offset: 2px;
				font-size: .875rem;
				padding: .5rem;
				display: flex;

				border-radius: 10rpx;
			}
		}

		.footer-item {
			display: flex;
			justify-content: space-between;
			padding: 0 .5rem .75rem;

			.footer-list {
				background-color: rgb(249 250 251);
				font-size: .875rem;
				border-radius: 10rpx;
				padding: .5rem;
				color: rgb(112 114 129);
				font-size: .8125rem;
			}
		}

		input {
			flex: 1;
			height: 100%;
			font-size: 28rpx;
			outline: none;
			border: 0;
			margin-right:20rpx;
			color: rgb(17 20 45);
		}

		.send {
			.btn {
				height: 46rpx;
				width: 46rpx;
				transform: translate(0, 0) rotate(70deg) skewX(0) skewY(0) scaleX(1) scaleY(1);
			}

			.loading {
				height: 51rpx;
				width: 51rpx;
				animation: rotate 1s linear infinite;
			}

			&.disabled {
				background-color: transparent;
			}

			@keyframes rotate {
				0% {
					transform: rotate(0);
				}

				100% {
					transform: rotate(360deg);
				}
			}
		}
	}
</style>